package com.cloud.common.handler;

import com.alibaba.fastjson.JSONObject;
import com.cloud.common.domain.Result;
import com.cloud.common.filter.OrderFilter;
import com.cloud.exception.CommonException;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 网关异常拦截器
 *
 * @author yzj
 */
@Configuration
public class GateWayExceptionHandler implements ErrorWebExceptionHandler, Ordered {

    @Override
    public Mono<Void> handle(ServerWebExchange webExchange, Throwable ex) {
        ServerHttpResponse response = webExchange.getResponse();
        if (response.isCommitted()) {
            return Mono.error(ex);
        }
        if (ex instanceof ResponseStatusException) {
            // 拦截异常信息
            ResponseStatusException statusException = (ResponseStatusException) ex;
            Integer code = statusException.getStatusCode().value();
            String message = statusException.getMessage();
            if (code == 503 || code == 404) {
                return webExchangeMessage(webExchange, CommonException.SERVER_NO_EXITS.getCode(),
                        CommonException.SERVER_NO_EXITS.getMsg() + message);
            }
            return webExchangeMessage(webExchange, CommonException.SERVER_URL_ERROR.getCode(),
                    CommonException.SERVER_URL_ERROR.getMsg() + message);
        }
        return webExchangeMessage(webExchange, CommonException.SYSTEM_ERROR.getCode(),
                CommonException.SYSTEM_ERROR.getMsg() + ex);
    }

    /**
     * ServerWebExchange 拦截消息输出
     *
     * @param webExchange
     * @param code
     * @param message
     * @return
     */
    private Mono<Void> webExchangeMessage(ServerWebExchange webExchange, Integer code, String message) {
        webExchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 这里需要指定响应头部信息,否则会中文乱码
        webExchange.getResponse().getHeaders().add("Content-Type",
                "application/json;charset=utf-8");
        DataBuffer buffer = webExchange.getResponse().bufferFactory()
                .wrap(JSONObject.toJSONString(Result.message(code, message)).getBytes(StandardCharsets.UTF_8));
        return webExchange.getResponse().writeWith(Flux.just(buffer));
    }

    @Override
    public int getOrder() {
        return OrderFilter.GATE_WAY_EXCEPTION;
    }
}